/**
 * @file CurrencyCommandImpl.java
 * Projet eCOM 2010 (Miage Descartes)
 * @author Doido Sébastien
 * @version 2
 * @brief Shell : Gestion des fonctionnalités relatives aux devises
 */
package ecom.shell;

import ecom.beans.EcomCustomerRemote;
import ecom.beans.EuroConvertorBean.Currency;
import ecom.shell.OutputCommandImpl.Outputs;
import ecom.shell.ShellConstantes.RESULT_ACTION;
import java.io.PrintStream;
import java.util.StringTokenizer;
import java.util.Vector;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

/**
 * @brief Shell : Gestion des fonctionnalités relatives aux devises
 * @author Sebastien
 */
public class CurrencyCommandImpl implements ShellCommand {

    private ShellContext _context = null;

    public CurrencyCommandImpl(ShellContext context) {
        _context = context;
    }

    /**
     * @brief Renvoie le nom de la commande
     * @return le nom de la commande
     */
    public String getName() {
        return "currency";
    }

    /**
     * @brief Renvoie la manière d'utiliser la commande
     * @return la manière d'utiliser la commande
     */
    public String getUsage() {
        StringBuffer sb = new StringBuffer();

        EcomCustomerRemote ecomCustomerBean = (EcomCustomerRemote) _context.getVar("customerBean");
        Vector<String> symbols = ecomCustomerBean.getCurrencySymbols();

        for (int i = 0; i < symbols.size(); ++i) {
            sb.append(symbols.get(i));
            if (i < symbols.size() - 1) {
                sb.append("|");
            }
        }
        return "currency " + sb;
    }

    /**
     * @brief Renvoie la description de la commande
     * @return la description de la commande
     */
    public String getShortDescription() {
        return "Set currency\n";
    }

    /**
     * @brief Exécute la commande
     * @param cmdline : commande à exécuter
     * @param out : flux d'affichage std
     * @param err : flux d'affichage err
     * @return les données à afficher
     * @throws java.lang.Exception : erreur durant l'exécution de la méthode
     */
    public String execute(String cmdline, PrintStream out, PrintStream err) {
        StringBuffer res = new StringBuffer();
        EcomCustomerRemote ecomCustomerBean = (EcomCustomerRemote) _context.getVar("customerBean");
        
        StringTokenizer st = new StringTokenizer(cmdline, " ");

        // Ignore cmd
        st.nextToken();

        // list all known currencies
        if (st.countTokens() == 0) {
            try {
                Vector<String> symbols = ecomCustomerBean.getCurrencySymbols();
                Outputs currentOutput = (Outputs) _context.getVar("output");
                return printList(out, symbols, currentOutput, ecomCustomerBean);
            } catch (Exception ex) {
                err.println("Error with currencies display");
            }
        }
        // trying to set a new currency
        else if (st.countTokens() == 1) {
            String newCurrency = st.nextToken().trim();
            Currency c;

            try {
                c = ecomCustomerBean.getCurrencyByName(newCurrency);
                res.append(_context.returnCode("New Currency : " + c + " (" + ecomCustomerBean.getCurrencyRealName(String.valueOf(c)) + ")", RESULT_ACTION.SUCCESS));
                _context.setVar("currency", c);
            } catch (Exception ex) {
                res.append(_context.returnCode(ex + " for " + getName() + " command", RESULT_ACTION.FAILED));
                err.println(ex + " for '" + getName() + "' command");
            }
        } else {
            res.append(_context.returnCode(Shell.INCORRECT_ARGS_NUMBER, RESULT_ACTION.FAILED));
                    err.println("\t" + Shell.INCORRECT_ARGS_NUMBER);
        }
        return res.toString();
    }

    /**
     * @brief Affichage de la liste des devises disponibles
     * @param out : flux d'affichage std
     * @param symbols : liste des devises disponibles
     * @param currentOutput : type de sortie attendue
     * @param ecomCustomerBean : bean remote client 
     * @return les données à afficher selon le type de sortie attendue
     */
    private String printList(PrintStream out, Vector<String> symbols, Outputs currentOutput, EcomCustomerRemote ecomCustomerBean) throws Exception {
        StringBuffer res = new StringBuffer();
        if (currentOutput.equals(Outputs.XML)) {
            Element currencies = new Element("currencies");
            org.jdom.Document document = new Document(currencies);

            for (String currency : symbols) {
                currencies.addContent(buildXMLNode(ecomCustomerBean.getCurrencyRealName(currency), currency));
            }
            XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat());
            return sortie.outputString(document);

        } else if (currentOutput.equals(Outputs.TEXT)) {
            res.append("####################" + "\n");
            res.append("# Known currencies #" + "\n");
            res.append("####################" + "\n");
            for (String c : symbols) {
                res.append("\t" + c + " - " + ecomCustomerBean.getCurrencyRealName(c) + "\n");
            }
        } else {
            res.append("\t /!\\ Output format '" + currentOutput + "' is known but not implementing for this command");
        }
        return res.toString();
    }

    /**
     * @brief Construit un arbre XML pour la devise à afficher
     * @param nameDevise : nom devise
     * @param idDevise : id devise
     * @return un arbre XML décrivant la devise à afficher
     */
    private Element buildXMLNode(String nameDevise, String idDevise) {
        Element currency = new Element("currency");
        
        Element name = new Element("name");
        Attribute id = new Attribute("id", idDevise);
        name.setAttribute(id);
        name.setText(nameDevise);
        currency.addContent(name);

        return currency;
    }
}
